package com.xmhmyh.generalframework.framework.security;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xmhmyh.generalframework.common.enums.YesOrNo;
import com.xmhmyh.generalframework.framework.exceptions.UserLoginException;
import com.xmhmyh.generalframework.project.sys.entity.*;
import com.xmhmyh.generalframework.project.sys.enums.UserStatus;
import com.xmhmyh.generalframework.project.sys.mapper.*;
import com.xmhmyh.generalframework.project.sys.service.IAccountService;
import com.xmhmyh.generalframework.project.sys.service.IMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: 于丁
 * @DateTime: 2020/7/20 7:08 下午
 */
@Service
public class MyUserDetailService implements UserDetailsService {

    @Resource
    private UserMapper userMapper;
    @Resource
    private UserRoleMapper userRoleMapper;
    @Resource
    private RoleMapper roleMapper;
    @Resource
    private RoleMenuMapper roleMenuMapper;
    @Resource
    private MenuMapper menuMapper;
    @Autowired
    private IMenuService menuService;
    @Autowired
    private IAccountService accountService;

    @Override
    public UserDetails loadUserByUsername(String userName) throws AuthenticationException {
        List<User> userList = findByUserName(userName);
        if (userList.size() != 1) {
            throw new UsernameNotFoundException("用户不存在");
        }
        User user = userList.get(0);
        if (user.getStatus().intValue() == UserStatus.FREEZE.getValue()) {
            throw new UserLoginException("用户已冻结");
        }
        // 获取相关的数据
        LoginUser loginUser = new LoginUser(user);
        // 获取用户权限信息
        List<Menu> menuList = menuService.getMenuByUserId(userList.get(0).getId());
        List<UserPermissionsOrRole> userPermissionsOrRoleList = new ArrayList<>();
        for (Menu menu : menuList) {
            String perms = menu.getPerms();
            String[] permsList = perms.split(",");
            for (int i = 0; i < permsList.length; i++) {
                userPermissionsOrRoleList.add(new UserPermissionsOrRole(permsList[i]));
            }
        }
        Map<Long, String> menuIdsMap = new HashMap<>();
        for (Menu menu : menuList) {
            menuIdsMap.put(menu.getId(), menu.getMenuName());
        }
        loginUser.setMenuIdsMap(menuIdsMap);
        loginUser.setUserPermissionsOrRoles(userPermissionsOrRoleList);
        return loginUser;
    }


    /**
     * @Author: 于丁
     * @Description: 根据用户名查找用户
     * @DateTime: 2020/7/21 7:54 下午
     * @Params:
     * @Return
     */
    public List<User> findByUserName(String userName) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserName, userName);
        List<User> userList = userMapper.selectList(queryWrapper);
        return userList;
    }

    /**
     * @Author: 于丁
     * @Description: 根据UserId获取用户的权限
     * @DateTime: 2020/7/21 2:12 下午
     * @Params:
     * @Return
     */
    public Set<String> getMenuByUserId(Long userId) {
        // 使用set去重处理
        Set<String> menuSet = new HashSet<>();
        // 获取用户的角色
        List<UserRole> userRoles = getUserRolesByUserId(userId);
        if (userRoles.size() == 0) {
            return menuSet;
        }
        List<Long> roleIds = userRoles.stream().map(userRole -> {
            return userRole.getRoleId();
        }).collect(Collectors.toList());
        if (roleIds.size() == 0) {
            return menuSet;
        }
        List<Role> roleList = roleMapper.selectBatchIds(roleIds);
        roleList.forEach(role -> {
            menuSet.add(role.getCode());
        });
        // 根据角色获取权限
        List<RoleMenu> rolePermissionsList = getRoleMenusByRoleIds(roleIds);
        List<Long> menuIds = rolePermissionsList.stream().map(rolePermissions -> {
            return rolePermissions.getMenuId();
        }).collect(Collectors.toList());
        // 添加用户权限
        if (menuIds.size() == 0) {
            return menuSet;
        }
        List<Menu> menuList = menuMapper.selectBatchIds(menuIds);
        menuList.forEach(menu -> {
            menuSet.add(menu.getPerms());
        });
        return menuSet;
    }

    /**
     * @Author: 于丁
     * @Description: 找到角色的菜单
     * @DateTime: 2020/7/21 8:04 下午
     * @Params:
     * @Return
     */
    private List<RoleMenu> getRoleMenusByRoleIds(List<Long> roleIds) {
        LambdaQueryWrapper<RoleMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(RoleMenu::getRoleId, roleIds);
        return roleMenuMapper.selectList(queryWrapper);
    }

    /**
     * @Author: 于丁
     * @Description: 找到用户的角色
     * @DateTime: 2020/7/21 8:04 下午
     * @Params:
     * @Return
     */
    private List<UserRole> getUserRolesByUserId(Long userId) {
        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRole::getUserId, userId);
        return userRoleMapper.selectList(queryWrapper);
    }
}
